
#include <assert.h>

#include "core/olisp_mem.h"
#include "utility/olisp_helpers.h"
#include "utility/olisp_assoc.h"

typedef struct assoc_pair_t assoc_pair_t;
struct assoc_pair_t
{
    lisp_hash_t     hash;
    obj_t *   elem;
};

int do_associate( assoc_context_t * ctx, lisp_hash_t hash, obj_t * elem )
{
    size_t n;
    assoc_pair_t * pair = 0;

    // try find already allocated element
    for( n = 0; n < ctx->length; ++ n )
        if( ctx->pairs[n].hash == hash )
            pair = &ctx->pairs[n];

    if( !pair )
    {
        // allocate one another element

        return 0;
    }

    return 1;
}

obj_t * get_associated_elem( assoc_context_t * ctx, obj_t * elem )
{
    size_t n;
    lisp_hash_t hash;

    // only identifiers could be substituted
    if( elem->vtbl->element_type != LISP_ELEM_ID )
        return elem;

    hash = id_as_hash( (id_obj_t *)elem );

    for( ;; )
    {
        for( n = 0; n < ctx->length; ++ n )
            if( ctx->pairs[n].hash == hash )
                return ctx->pairs[n].elem;

        if( ctx->prev_ctx )
            ctx = ctx->prev_ctx;
        else
            break;
    }

    return elem;
}

void dispose_assoc_context( assoc_context_t * ctx )
{
    if( ctx->pairs )
    {
        lisp_free( ctx->pairs );
    }

    ctx->pairs = 0;
    ctx->length = ctx->allocated = 0;
}
